#!/bin/bash
source /etc/profile

# 设置默认的 JDK 路径，允许通过环境变量覆盖
#JAVA_HOME=${JAVA_HOME:-/opt/jdk1.7.0_80}
#export JAVA_HOME
#export PATH=$JAVA_HOME/bin:$PATH
#export LC_ALL=zh_CN.UTF-8

# 配置参数
STARTUP_TIMEOUT=30      # 启动超时时间（秒）
SHUTDOWN_TIMEOUT=15     # 关闭超时时间（秒）
CHECK_INTERVAL=1        # 检查间隔（秒）
LOCK_DIR="/tmp/acs_locks"  # 锁文件目录

# 创建锁文件目录
mkdir -p "$LOCK_DIR"


# --- 检查异常acs_server ---
ACS_CHECK_PROCESS_NAME="acs_server.jar"

echo "=== 开始检查所有 '$ACS_CHECK_PROCESS_NAME' 进程的端口状态 ==="

# 1. 获取所有相关进程的PID列表
ACS_CHECK_PIDS=$(ps -ef | grep "$ACS_CHECK_PROCESS_NAME" | grep -v 'grep' | awk '{print $2}')

# 2. 检查是否找到了任何进程
if [ -z "$ACS_CHECK_PIDS" ]; then
    echo "未找到任何正在运行的 '$ACS_CHECK_PROCESS_NAME' 进程。"
    echo "==================== 检查完成 ===================="
    #exit 0
fi

echo "发现以下 '$ACS_CHECK_PROCESS_NAME' 进程: $ACS_CHECK_PIDS"

# 3. 初始化一个用于存储“问题进程”PID的列表
ACS_CHECK_PIDS_TO_KILL=""

# 4. 循环遍历所有找到的PID，进行检查
for ACS_CHECK_PID in $ACS_CHECK_PIDS; do
    # 使用 ss 精确检查该PID是否在监听端口
    if ss -plnt | grep -q "pid=$ACS_CHECK_PID\b"; then
        echo "  [PID: $ACS_CHECK_PID] ... ✅ 状态正常，端口在监听中。"
    else
        echo "  [PID: $ACS_CHECK_PID] ... ❌ 状态异常，未监听端口！已加入待处理列表。"
        # 将有问题的PID追加到待处理列表
        ACS_CHECK_PIDS_TO_KILL="$ACS_CHECK_PIDS_TO_KILL $ACS_CHECK_PID"
    fi
done

echo "====================================================="

# 5. 检查待处理列表，如果非空，则执行批量结束操作
if [ -z "$ACS_CHECK_PIDS_TO_KILL" ]; then
    echo "所有 '$ACS_CHECK_PROCESS_NAME' 进程均在正常监听端口，无需任何操作。"
else
    # 使用 xargs 去除前后的空格，让输出更美观
    ACS_CHECK_CLEANED_PIDS=$(echo "$ACS_CHECK_PIDS_TO_KILL" | xargs)
    
    echo "发现以下进程没有正常监听端口，准备批量结束:"
    echo "  -> $ACS_CHECK_CLEANED_PIDS"
    
    # 执行批量 kill 命令
    kill -9 $ACS_CHECK_CLEANED_PIDS
    
    echo "批量结束命令已发送。"
    
    # 可以选择增加一个等待和确认的步骤
    sleep 2
    echo "正在确认状态..."
    for ACS_CHECK_PID in $ACS_CHECK_CLEANED_PIDS; do
        if ! ps -p "$ACS_CHECK_PID" > /dev/null; then
            echo "  [PID: $ACS_CHECK_PID] ... ✅ 已成功结束。"
        else
            echo "  [PID: $ACS_CHECK_PID] ... ⚠️ 仍未结束，可能需要强制处理 (kill -9 $ACS_CHECK_PID)。"
        fi
    done
fi

echo "==================== 检查异常acs_server进程完成 ===================="



usage() {
    echo "Usage: $0 -s [stop|start|restart|status] -p port"
    echo "Example: $0 -s start -p 8080"
}


# 如果没有参数，则显示用法
if [ $# -eq 0 ]; then
    usage
    exit 1
fi

# 获取传入的参数
while getopts ":s:p:" opt; do
    case $opt in
        s)
            s=$OPTARG
            if [[ "$s" != "start" && "$s" != "stop" && "$s" != "restart" && "$s" != "status" ]]; then
                echo "错误: -s 参数必须是 start|stop|restart|status 之一"
                usage
                exit 1
            fi
            ;;
        p)
            port=$OPTARG
            if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
                echo "错误: -p 参数必须是 1-65535 之间的有效端口号"
                usage
                exit 1
            fi
            ;;
        \?)
            echo "错误: 无效的参数 -$OPTARG"
            usage
            exit 1
            ;;
    esac
done

# 检查必需参数
if [ -z "$s" ] || [ -z "$port" ]; then
    echo "错误: 缺少必需参数"
    usage
    exit 1
fi

# 防止重复执行的锁机制
LOCK_FILE="$LOCK_DIR/acs_${port}.lock"

acquire_lock() {
    local timeout=10
    local count=0
    
    while [ $count -lt $timeout ]; do
        if (set -C; echo $$ > "$LOCK_FILE") 2>/dev/null; then
            # 设置陷阱，确保脚本退出时释放锁
            trap 'rm -f "$LOCK_FILE"; exit' INT TERM EXIT
            return 0
        fi
        
        # 检查锁文件中的PID是否仍在运行
        if [ -f "$LOCK_FILE" ]; then
            local lock_pid=$(cat "$LOCK_FILE" 2>/dev/null)
            if ! kill -0 "$lock_pid" 2>/dev/null; then
                echo "清理僵尸锁文件: $LOCK_FILE"
                rm -f "$LOCK_FILE"
                continue
            fi
        fi
        
        echo "等待其他操作完成... ($count/$timeout)"
        sleep 1
        count=$((count + 1))
    done
    
    echo "错误: 无法获取锁，可能有其他操作正在进行"
    exit 1
}

release_lock() {
    rm -f "$LOCK_FILE"
    trap - INT TERM EXIT
}

# 获取指定端口的所有 PID（改进版本）
get_pids_by_port() {
    local port=$1
    local pids=""
    
    # 方法1: 使用 ss 命令（推荐）
    if command -v ss >/dev/null 2>&1; then
        pids=$(ss -ltnp 2>/dev/null | grep ":$port " | sed -n 's/.*pid=\([0-9]*\).*/\1/p' | sort -u | tr '\n' ' ')
    fi
    
    # 方法2: 使用 netstat 作为备选
    #if [ -z "$pids" ] && command -v netstat >/dev/null 2>&1; then
    #    pids=$(netstat -ltnp 2>/dev/null | grep ":$port " | awk '{print $7}' | cut -d'/' -f1 | grep -E '^[0-9]+$' | sort -u | tr '\n' ' ')
    #fi
    
    # 方法3: 使用 lsof 作为最后的备选
    # if [ -z "$pids" ] && command -v lsof >/dev/null 2>&1; then
    #     pids=$(lsof -ti:$port 2>/dev/null | sort -u | tr '\n' ' ')
    #fi
    
    # 过滤掉无效的PID
    local valid_pids=""
    for pid in $pids; do
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            valid_pids="$valid_pids $pid"
        fi
    done
    
    echo "$valid_pids" | sed 's/^ *//' | sed 's/ *$//'
}

# 检查端口是否被占用
is_port_in_use() {
    local port=$1
    
    # 使用多种方法检查端口占用
    if command -v ss >/dev/null 2>&1; then
        ss -ltn 2>/dev/null | grep -q ":$port "
    elif command -v netstat >/dev/null 2>&1; then
        netstat -ltn 2>/dev/null | grep -q ":$port "
    else
        # 使用 /proc/net/tcp 作为最后备选
        local hex_port=$(printf "%04X" $port)
        grep -q ":$hex_port " /proc/net/tcp 2>/dev/null
    fi
}

# 等待端口释放
wait_for_port_free() {
    local port=$1
    local timeout=$2
    local count=0
    
    echo "等待端口 $port 释放..."
    while [ $count -lt $timeout ]; do
        if ! is_port_in_use $port; then
            echo "端口 $port 已释放"
            return 0
        fi
        sleep $CHECK_INTERVAL
        count=$((count + CHECK_INTERVAL))
        echo "等待端口释放... ($count/$timeout 秒)"
    done
    
    echo "警告: 端口 $port 在 $timeout 秒内未释放"
    return 1
}

# 等待端口被占用（服务启动）
wait_for_port_used() {
    local port=$1
    local timeout=$2
    local count=0
    
    echo "等待服务在端口 $port 启动..."
    while [ $count -lt $timeout ]; do
        if is_port_in_use $port; then
            echo "服务已在端口 $port 启动"
            return 0
        fi
        sleep $CHECK_INTERVAL
        count=$((count + CHECK_INTERVAL))
        echo "等待服务启动... ($count/$timeout 秒)"
    done
    
    echo "错误: 服务在 $timeout 秒内未在端口 $port 启动"
    return 1
}

# 强制终止进程的函数（改进版本）
kill_processes() {
    local pids=$1
    local port=$2
    
    if [ -z "$pids" ]; then
        echo "未找到运行在端口 $port 的进程"
        return 0
    fi
    
    echo "找到运行在端口 $port 的进程: $pids"
    
    # 发送 SIGTERM 信号
    for pid in $pids; do
        if [ -n "$pid" ] && kill -0 $pid 2>/dev/null; then
            echo "向进程 $pid 发送 SIGTERM 信号..."
            kill $pid 2>/dev/null
        fi
    done
    
    # 等待进程优雅退出
    local wait_count=0
    local all_stopped=false
    
    while [ $wait_count -lt $SHUTDOWN_TIMEOUT ]; do
        all_stopped=true
        for pid in $pids; do
            if [ -n "$pid" ] && kill -0 $pid 2>/dev/null; then
                all_stopped=false
                break
            fi
        done
        
        if $all_stopped; then
            echo "所有进程已优雅退出"
            break
        fi
        
        sleep $CHECK_INTERVAL
        wait_count=$((wait_count + CHECK_INTERVAL))
        echo "等待进程退出... ($wait_count/$SHUTDOWN_TIMEOUT 秒)"
    done
    
    # 如果进程仍在运行，强制终止
    if ! $all_stopped; then
        echo "部分进程未响应 SIGTERM，使用 SIGKILL 强制终止..."
        for pid in $pids; do
            if [ -n "$pid" ] && kill -0 $pid 2>/dev/null; then
                echo "强制终止进程 $pid"
                kill -9 $pid 2>/dev/null
            fi
        done
        sleep 2
    fi
    
    # 等待端口释放
    wait_for_port_free $port $SHUTDOWN_TIMEOUT
}

# 验证 ACS 进程是否健康启动
verify_acs_health() {
    local port=$1
    local max_checks=5
    local check_count=0
    
    echo "验证 ACS 服务健康状态..."
    
    while [ $check_count -lt $max_checks ]; do
        local pids=$(get_pids_by_port $port)
        if [ -n "$pids" ] && is_port_in_use $port; then
            # 检查进程是否稳定运行
            sleep 2
            local new_pids=$(get_pids_by_port $port)
            if [ "$pids" = "$new_pids" ]; then
                echo "ACS 服务健康检查通过，PID: $pids"
                return 0
            fi
        fi
        
        check_count=$((check_count + 1))
        echo "健康检查失败，重试 $check_count/$max_checks"
        sleep 2
    done
    
    echo "警告: ACS 服务健康检查失败"
    return 1
}

# 查找 bin 目录
find_bin_path() {
    local port=$1
    local binPath=""
    
    # 尝试多种路径模式
    local search_paths=(
        "/opt/acs/*$port*/bin"
        "/opt/acs/*/bin"
        "/usr/local/acs/*$port*/bin"
        "/home/*/acs/*$port*/bin"
        "/home/ACS/*/bin"
    )
    
    for pattern in "${search_paths[@]}"; do
        binPath=$(find $(dirname "$pattern") -type d -name 'bin' 2>/dev/null | grep "$port" | head -1)
        if [ -n "$binPath" ] && [ -d "$binPath" ] && [ -f "$binPath/startup.sh" ]; then
            echo "$binPath"
            return 0
        fi
    done
    
    # 如果没找到特定端口的，尝试通用路径
    binPath=$(find /home/ACS/ -type d -name 'bin' 2>/dev/null | head -1)
    if [ -n "$binPath" ] && [ -d "$binPath" ] && [ -f "$binPath/startup.sh" ]; then
        echo "$binPath"
        return 0
    fi
    
    return 1
}

# 获取锁
acquire_lock

# 查找 bin 目录
binPath=$(find_bin_path $port)

if [ -z "$binPath" ]; then
    echo "错误: 未找到对应端口 $port 的 bin 目录或 startup.sh 文件"
    echo "请检查 ACS 安装路径和配置"
    release_lock
    exit 1
fi

echo "使用 bin 目录: $binPath"

# 执行相应操作
case $s in
    restart)
        echo "======== 重启 ACS 服务 (端口: $port) ========"
        
        # 停止现有进程
        pids=$(get_pids_by_port $port)
        if [ -n "$pids" ]; then
            echo "停止现有 ACS 进程..."
            kill_processes "$pids" $port
        else
            echo "ACS 进程未运行在端口 $port"
        fi
        
        # 确保端口完全释放
        if is_port_in_use $port; then
            echo "端口仍被占用，等待释放..."
            if ! wait_for_port_free $port $SHUTDOWN_TIMEOUT; then
                echo "错误: 无法释放端口 $port，重启失败"
                release_lock
                exit 1
            fi
        fi
        
        # 启动服务
        echo "启动 ACS 服务..."
        cd "$binPath" || { 
            echo "错误: 无法切换到目录 $binPath"
            release_lock
            exit 1
        }
        
        nohup ./startup.sh >/dev/null 2>&1 &
        startup_pid=$!
        
        # 等待服务启动
        if wait_for_port_used $port $STARTUP_TIMEOUT; then
            if verify_acs_health $port; then
                echo "✓ ACS 重启成功"
            else
                echo "⚠ ACS 已启动但健康检查失败，请查看日志"
            fi
        else
            echo "✗ ACS 启动失败，请检查配置和日志"
            release_lock
            exit 1
        fi
        ;;
        
    start)
        echo "======== 启动 ACS 服务 (端口: $port) ========"
        
        # 检查是否已经运行
        pids=$(get_pids_by_port $port)
        if [ -n "$pids" ]; then
            echo "ACS 已在端口 $port 运行，PID: $pids"
            if verify_acs_health $port; then
                echo "✓ ACS 服务运行正常"
                release_lock
                exit 0
            else
                echo "⚠ ACS 服务运行异常，建议重启"
                release_lock
                exit 1
            fi
        fi
        
        # 检查端口是否被其他进程占用
        if is_port_in_use $port; then
            echo "错误: 端口 $port 被其他进程占用"
            release_lock
            exit 1
        fi
        
        # 启动服务
        echo "启动 ACS 服务..."
        cd "$binPath" || { 
            echo "错误: 无法切换到目录 $binPath"
            release_lock
            exit 1
        }
        
        nohup ./startup.sh >/dev/null 2>&1 &
        
        # 等待服务启动
        if wait_for_port_used $port $STARTUP_TIMEOUT; then
            if verify_acs_health $port; then
                echo "✓ ACS 启动成功"
            else
                echo "⚠ ACS 已启动但健康检查失败，请查看日志"
            fi
        else
            echo "✗ ACS 启动失败，请检查配置和日志"
            release_lock
            exit 1
        fi
        ;;
        
    stop)
        echo "======== 停止 ACS 服务 (端口: $port) ========"
        
        pids=$(get_pids_by_port $port)
        if [ -z "$pids" ]; then
            echo "未找到运行在端口 $port 的 ACS 进程"
            release_lock
            exit 0
        fi
        
        kill_processes "$pids" $port
        echo "✓ ACS 停止完成"
        ;;
        
    status)
        echo "======== ACS 服务状态 (端口: $port) ========"
        
        pids=$(get_pids_by_port $port)
        if [ -z "$pids" ]; then
            echo "✗ ACS 未在端口 $port 运行"
            release_lock
            exit 1
        else
            echo "✓ ACS 正在端口 $port 运行，PID: $pids"
            
            # 显示详细信息
            for pid in $pids; do
                if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
                    local start_time=$(ps -o lstart= -p $pid 2>/dev/null | sed 's/^ *//')
                    local cpu_mem=$(ps -o %cpu,%mem,vsz,rss -p $pid --no-headers 2>/dev/null)
                    echo "  PID $pid - 启动时间: $start_time"
                    echo "  PID $pid - CPU/MEM/VSZ/RSS: $cpu_mem"
                fi
            done
            
            # 进行健康检查
            if verify_acs_health $port; then
                echo "✓ ACS 服务健康状态良好"
            else
                echo "⚠ ACS 服务可能存在问题"
                release_lock
                exit 1
            fi
        fi
        ;;
esac

# 释放锁
release_lock
echo "======== 操作完成 ========"